/**
 * @fileoverview
 * This script defines a service class for retrieving data from flyatlas.
 * @author <a href="http://purl.org/net/aliman">Alistair Miles</a>
 * @version $Revision:538 $ on $Date: 2008-08-27 09:08:41 +0100 (Wed, 27 Aug 2008) $ by $Author: aliman $
 * @requires flyui.util
 * @requires flyui.sparql.Service
 * @requires YAHOO.util.Connect
 * For license terms see http://flyui.googlecode.com
 */


flyui.namespace("flyui.flyatlas");


/**
 * @class
 * @extends flyui.sparql.Service
 */
flyui.flyatlas.Service = function() {};


// extend
flyui.flyatlas.Service.prototype = new flyui.sparql.Service();


/**
 * @param {String} affyId
 * @param {Function} success callback will be passed an array of flyui.flyatlas.AssayGroup objects
 * @param {Function} failure callback will be passed a YUI failure case response object
 * @member flyui.flyatlas.Service
 * @throws flyui.UnexpectedException
 */
flyui.flyatlas.Service.prototype.getAssaysByAffyProbeId = function( affyId, success, failure ) {
    var _context = "flyui.flyatlas.Service.prototype.getAssaysByAffyProbeId";
    try {
        flyui.info("request: "+affyId, _context);
        var chain = flyui.chain(flyui.flyatlas.Service.responseToAssayGroups, success);
        var query = this._buildQueryForGetAssaysByProbeId(affyId);
        flyui.debug("query: "+query, _context);
        this.postQuery(query, chain, failure);
    } catch (error) {
        throw new flyui.UnexpectedException(_context, error);
    }
};


/**
 * @param {String} flybaseId
 * @param {Function} success callback will be passed an array of flyui.flyatlas.AssayGroup objects
 * @param {Function} failure callback will be passed a YUI failure case response object
 * @member flyui.flyatlas.Service
 */
flyui.flyatlas.Service.prototype.getAssaysByFlybaseGeneId = function( flybaseId, success, failure ) {
    var _context = "flyui.flyatlas.Service.prototype.getAssaysByFlybaseGeneId";
    try {
        flyui.info("request: "+flybaseId, _context);
        var chain = flyui.chain(flyui.flyatlas.Service.responseToAssayGroups, success);
        var query = this._buildQueryForGetAssaysByFlybaseGeneId(flybaseId);
        flyui.debug("query: "+query, _context);
        this.postQuery(query, chain, failure);
    } catch (error) {
        throw new flyui.UnexpectedException(_context, error);
    }
}


/**
 * @param {Object} response a YUI success case response object
 * @type Array<flyui.flyatlas.AssayGroup>
 * @throws flyui.UnexpectedException
 * @static
 */
flyui.flyatlas.Service.responseToAssayGroups = function( response ) {   
    var _context = "flyui.flyatlas.Service.responseToAssayGroups";   
    try {
        flyui.debug("response status: "+response.status, _context); 
        flyui.debug("parsing response as json: "+response.responseText, _context);
        var resultSet = YAHOO.lang.JSON.parse(response.responseText);
        flyui.debug("convert result set to an array of genes", _context);
        var groups = flyui.flyatlas.AssayGroup.newInstancesFromResultSet(resultSet);
        return groups;
    } catch (error) {
        throw new flyui.UnexpectedException(_context, error);
    }
};


/**
 * @private
 * @param {String} query
 * @type String
 * @throws flyui.UnexpectedException
 */
flyui.flyatlas.Service.prototype._buildQueryForGetAssaysByProbeId = function( affyId ) {
    var _context = "flyui.flyatlas.Service.prototype._buildQueryForGetAssaysByProbeId";
    try {
        
        var head =          "PREFIX xs: <http://www.w3.org/2001/XMLSchema#> \n" + 
                            "PREFIX : <http://purl.org/NET/flyatlas/schema#> ";
                    
        var body_start =    "SELECT * WHERE { \n" +
                            "?probedata :affy_id \""+affyId+"\"^^xs:string , ?affy_id ; a :ProbeData ; \n" +
                            "  :fly_present ?whole_present ; \n" +
                            "  :fly_mean ?whole_mean ; \n" +
                            "  :fly_SEM ?whole_sem ; ";
        
        function body_part( tissue ) {
        	return          "  :"+tissue+" [ \n" + 
    						"    a :TissueVals ; \n" +
    						"    :t_change ?"+tissue+"_change ; \n" +
    						"    :mean ?"+tissue+"_mean ; \n" +
    						"    :sem ?"+tissue+"_sem ; \n" +
    						"    :present ?"+tissue+"_present ; \n" +
    						"    :ratio ?"+tissue+"_ratio ; \n" +
    						"  ] ; "
        }
    
        var body_end =      " . }";
        
        var query = head;
        query += body_start;
        for (var i=0; i<flyui.flyatlas.tissues.length; i++) { 
            var tissue = flyui.flyatlas.tissues[i];
            if (tissue != "whole") {
                query += body_part(flyui.flyatlas.tissues[i]); 
            }
        }
        query += body_end;
        return query;

    } catch (error) {
        throw new flyui.UnexpectedException(_context, error);
    }
}

/**
 * @private
 * @param {String} query
 * @type String
 * @throws flyui.UnexpectedException
 */
flyui.flyatlas.Service.prototype._buildQueryForGetAssaysByFlybaseGeneId = function( flybaseId ) {
    var _context = "flyui.flyatlas.Service.prototype._buildQueryForGetAssaysByFlybaseGeneId";
    try {
        var head =          "PREFIX xs: <http://www.w3.org/2001/XMLSchema#> \n" + 
                            "PREFIX : <http://purl.org/NET/flyatlas/schema#> \n" +
                            "PREFIX fb: <http://openflydata.org/id/flybase/feature/> \n";
                    
        var body_start =    "SELECT * WHERE { \n" +
                            "?probedata :gene fb:"+flybaseId+"; \n" +
                            "  a :ProbeData ; \n" +
                            "  :affy_id ?affy_id ; \n" +
                            "  :fly_present ?whole_present ; \n" +
                            "  :fly_mean ?whole_mean ; \n" +
                            "  :fly_SEM ?whole_sem ; \n";
        
        function body_part( tissue ) {
        	return          "  :"+tissue+" [ \n" + 
    						"    a :TissueVals ; \n" +
    						"    :t_change ?"+tissue+"_change ; \n" +
    						"    :mean ?"+tissue+"_mean ; \n" +
    						"    :sem ?"+tissue+"_sem ; \n" +
    						"    :present ?"+tissue+"_present ; \n" +
    						"    :ratio ?"+tissue+"_ratio ; \n" +
    						"  ] ; \n"
        }
    
        var body_end =      " . }";
        
        var query = head;
        query += body_start;
        for (var i=0; i<flyui.flyatlas.tissues.length; i++) { 
            var tissue = flyui.flyatlas.tissues[i];
            if (tissue != "whole") {
                query += body_part(flyui.flyatlas.tissues[i]); 
            }
        }
        query += body_end;
        return query;

    } catch (error) {
        throw new flyui.UnexpectedException(_context, error);
    }
}


/**
 * @class
 */
flyui.flyatlas.AssayGroup = function() {

    /**
     * @type String
     */
    this.affy_id = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.whole = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.brain = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.head = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.crop = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.midgut = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.hindgut = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.tubule = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.ovary = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.testis = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.acc = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.l_tubule = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.l_fatbody = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.ta_ganglion = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.carcass = null;
    
    /**
     * @type flyui.flyatlas.Assay
     */
    this.sgland = null;
    
};


/**
 * @param {Object} resultSet
 * @type Array<flyui.flyatlas.AssayGroup>
 * @throws flyui.UnexpectedException
 */
flyui.flyatlas.AssayGroup.newInstancesFromResultSet = function( resultSet ) {
    var _context = "flyui.flyatlas.AssayGroup.newInstancesFromResultSet";
    try {
    	var groups = [];
    	for (var i=0; i<resultSet.results.bindings.length; i++) {
    		var binding = resultSet.results.bindings[i];
    		groups[groups.length] = flyui.flyatlas.AssayGroup.newInstanceFromBinding(binding);
    	}
    	return groups;
    } catch (error) {
        throw new flyui.UnexpectedException(_context, error);
    }
};


/**
 * @param {Object} binding
 * @type flyui.flyatlas.AssayGroup
 * @throws flyui.UnexpectedException
 */
flyui.flyatlas.AssayGroup.newInstanceFromBinding = function( binding ) {
    var _context = "flyui.flyatlas.AssayGroup.newInstanceFromBinding";
    try {
    	var group = new flyui.flyatlas.AssayGroup();
    	
    	group.affy_id = binding["affy_id"].value;
    	
    	// populate assays
    	for (var i=0; i<flyui.flyatlas.tissues.length; i++) {
    		var tissue = flyui.flyatlas.tissues[i];
    		group[tissue] = flyui.flyatlas.Assay.newInstanceFromBinding(binding, tissue);
    	}
    	
        return group;	
    } catch (error) {
        throw new flyui.UnexpectedException(_context, error);
    }
};


/**
 * @class
 */
flyui.flyatlas.Assay = function() {

    /**
     * @type Number
     */
    this.mean = null;
    
    /**
     * @type Number
     */
    this.present = null;
    
    /**
     * @type Number
     */
    this.sem = null;
    
    /**
     * @type String
     */
    this.change = null;
    
    /**
     * @type Number
     */
    this.ratio = null;
    
};

/**
 * @param {Object} binding
 * @param {String} tissue
 * @type flyui.flyatlas.Assay
 * @static
 * @throws flyui.UnexpectedException
 */
flyui.flyatlas.Assay.newInstanceFromBinding = function( binding, tissue ) {
    var _context = "flyui.flyatlas.Assay.newInstanceFromBinding";
    try {
    	var assay = new flyui.flyatlas.Assay();
    	
    	var sharedProps = ["mean", "sem", "present"];
    	
    	// populate shared props
    	for (var i=0; i<sharedProps.length; i++) {
    		var p = sharedProps[i];
    		assay[p] = binding[tissue+"_"+p].value;
    	}
    
        var otherProps = ["ratio", "change"];
        
        if (tissue == "whole") {
        	// force prop values for whole fly
            assay.ratio = 1;
            assay.change = "None";    	
        }
        else {
    	    for (var i=0; i<otherProps.length; i++) {
    	        var op = otherProps[i];
    	        if (binding[tissue+"_"+op]) {
    	            assay[op] = binding[tissue+"_"+op].value;
    	        }
    	    }
        }
    
        return assay;
    } catch (error) {
        throw new flyui.UnexpectedException(_context, error);
    }
};


/**
 * @type Array<String>
 */
flyui.flyatlas.tissues = [
    "whole",
    "brain",
    "head",
    "crop",
    "midgut",
    "hindgut",
    "tubule",
    "ovary",
    "testis",
    "acc",
    "l_tubule",
    "l_fatbody",
    "ta_ganglion",
    "carcass",
    "sgland"
];
